Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Programmer's Overview / Part 2 - The QuickDraw GX Programming Cookbook
Chapter 6 - Handling Graphics


Selecting Shapes

This programming recipe adds a new feature to the application created in the previous recipe. With the code from this recipe, you can allow users to select a previously created path, as shown in Figure 6-2.

Figure 6-2 Selecting a path shape

When the user presses the mouse button, the code in this recipe determines if the location was close to any previously created path. If so, the code deselects the previously selected path by erasing its geometry control handles, and selects the new path by drawing its geometry control handles.

If the place where the user clicks the mouse isn't close to any previously selected path, the recipe uses code from the previous recipe to allow the user
to create a new path.

Overview of Recipe Steps

The steps in this recipe show you how to:

    1. Determine if the user is selecting a path
    2. Deselect the previously selected path
    3. Select the newly selected path

You need to follow the instructions in each step of this recipe to implement the path-selecting feature.

Functions Used in This Recipe

QuickDraw GX functions used in this recipe:
GXHitTestPicture"Picture Shapes"
QuickDraw GX Graphics
GXSetShapeHitTest"Transform Objects"
QuickDraw GX Objects
GXDisposeShape"Shape Objects"
QuickDraw GX Objects
GXCloneShape"Shape Objects"
QuickDraw GX Objects
GXGetShapePoints"Geometric Shapes"
QuickDraw GX Graphics

This recipe gives a brief description of these functions; you can find complete reference information for these functions in the Inside Macintosh suite of books.

Recipe Step Descriptions

In this section, each step is described individually.

  1. Determine that the user is selecting a path

    In the MyContentClick sample function presented in Step 3 of the previous recipe (on page 185), you converted the mouse location from QuickDraw global coordinates to QuickDraw GX local coordinates and then called the MyHandleCreatePath sample function. For this recipe, you need to change the implementation of that function so that you can determine if the user is selecting an existing path rather than creating a new path. You can do this by calling a new sample function, MyHandleSelectPath. Add these lines of code to your MyContentClick function:

    boolean handled = false;

    handled = MyHandleSelectPath(&localPoint);

    if (! handled)
    MyHandleCreatePath(&localPoint);

    The MyHandleSelectPath function determines whether an existing path shape was hit and, if so, it

    • deselects the currently selected path
    • selects the hit path
    • returns true to indicate that the user was selecting a path

      Here is the flow of control for the MyHandleSelectPath function:

      boolean MyHandleSelectPath(gxPoint *hitPoint)
      {
      gxHitTestInfo result;
      gxShape shapeHit;

          if (gCurrent->pointCount == 0) {
      shapeHit = GXHitTestPicture(gCurrent->picture,
      hitPoint,
      &result, 1, 1);

              if ((result.what & gxGeometryPart) != 0) {
      /* Deselect current path -- see Step 2. */
      /* Select new path -- see Step 3. */

                  return true;
      }
      }
      return false;
      }

      This function first examines the current point count to be sure that it is 0. If the point count is not 0, then the user is in the middle of creating a new path and you don't want to allow them to select a previous one!

      This function calls the GXHitTestPicture function to determine if any
      path shape in the window's picture was hit by the mouse click. The GXHitTestPicture function returns a reference to the hit shape as
      the function result and also returns information about the hit shape in the result parameter. The what field of this parameter describes what part
      of the hit shape was hit.

      In this recipe, you are only interested in whether the user hit the geometry part of the path shape, so you can test the what field of the result parameter against the constant gxGeometryPart. In fact, you can use the hit-test parameters property of the transform objects of the path shapes to specify that QuickDraw GX only consider the geometry parts of the path shapes when hit-testing them. You use the GXSetShapeHitTest function to set a shape's hit-test parameters, as in this function call:

      GXSetShapeHitTest(gCurrent->selectedPath, 
      gxGeometryPart,
      ff(5));

      This function call specifies that the path should be hit-tested only on its geometry part and with a tolerance of 5.0.

      You should set the hit-test parameters of your path shapes when you create them, in the MyHandleCreatePath function defined in the previous recipe.

  2. Deselect the previously selected path

    Your MyHandleSelectPath function determines if the user is selecting a path. If so, you need to deselect the previously selected path, which you can do by erasing and disposing of its geometry control handles:

    if (gCurrent->selectedPath != nil) {
    MyErasePathControlHandles();
    MyDisposePathControlHandles();
    GXDisposeShape(gCurrent->selectedPath);
    }

    Notice that this code calls the GXDisposeShape function on the currently selected path. This function lowers the owner count of that shape, but it does not actually free the memory used by the shape because there is still a reference to the shape in the window's picture.

  3. Select the newly selected path

    After you deselect the previously selected path, you can select the newly selected path by storing a reference to it in the document information structure:

    gCurrent->selectedPath = GXCloneShape(result.which);

    This assignment statement copies a reference to the newly selected path shape into the selectedPath field of the document information structure. By calling the GXCloneShape function, it also increments the owner count of this path shape to reflect the new reference to it. When you deselect this path shape (in Step 2), the owner count is decremented back to 1, reflecting the reference to the shape contained in the window picture.

    Now you can create and draw geometry control handles for the newly selected path:

    MyCreatePathControlHandles(gCurrent->selectedPath);
    MyDrawPathControlHandles();

    You can define a MyCreatePathControlHandles sample function to create all four geometry control handles with this code:

    void MyCreatePathControlHandles(gxShape pathToSelect)
    {
    int index;
    gxShape aControl;
    gxPoint geometryPoints[kNumOfControls];

        GXGetShapePoints(pathToSelect, 1, 
    kNumOfControls, geometryPoints);

        for (index = 0; index <kNumOfControls; index++) {
    MyCreateControlHandle(&aControl, &geometryPoints[index]);
    gCurrent->controls[index] = aControl;
    }
    }

    This function uses the QuickDraw GX function GXGetShapePoints to fill an array with copies of the geometric points of the selected path. Then, the function uses the MyCreateControlHandle function (which you defined on page 188) to create a geometry control handle for each geometric point in the path shape.

Related Recipes

The previous recipe, "Creating Geometric Shapes" beginning on page 179, shows how to allow the user to create path shapes. You must complete the steps of that recipe before using this recipe.

The following two recipes show how to add more functionality to the path-
editing program:

The last recipe in this chapter, "Dragging Shapes Using Offscreen Bitmaps," beginning on page 217, shows how to allow the user to drag colored circles around a window. This recipe uses an offscreen bitmap to smooth the redrawing used for dragging feedback.

The recipes in Chapter 4, "Using the QuickDraw GX Environment," show you how to initialize QuickDraw GX and set up the QuickDraw GX debugging facilities. You should read the recipes in that chapter before using any recipes in this chapter.

The recipes in Chapter 5, "Using Macintosh Windows," show you how to create Macintosh windows, attach QuickDraw GX view ports to them, and implement zooming, resizing, and scrolling. You need to be familiar with the information in that chapter before you can display QuickDraw GX graphics
in a Macintosh window.

The recipes in Chapter 6, "Handling Typography," show you how to create and manipulate typographic shapes.

The recipes in Chapter 8, "Printing," show you how to send your graphics and typographic images to a printer.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996